package mapper

import (
	"context"
	"gorm.io/gorm"
	constans "mall/services/product/rpc/consts"
	"mall/services/product/rpc/internal/domain/bo"
	"mall/services/product/rpc/internal/domain/do"
	"mall/services/product/rpc/internal/initialize/mysql"
	"mall/services/product/rpc/internal/mapper/entity"
	"time"
)

var skuAllColumn = "sku_id, create_time, update_time, spu_id, sku_name, attrs, img_url, price_fee, market_price_fee," +
	" party_code, model_id, weight, volume, status"

var skuAllColumnJoin = "sku.sku_id as sku_id, sku.create_time as create_time, " +
	"sku.update_time as update_time, sku.spu_id as spu_id, sku.sku_name as sku_name, " +
	"sku.attrs as attrs, sku.img_url as img_url, sku.price_fee as price_fee, " +
	"sku.market_price_fee as market_price_fee,sku.party_code as party_code, sku.model_id as model_id, " +
	"sku.weight as weight , sku.volume as volume , sku.status as status"

type SkuMapper struct {
}

func NewSkuMapper() *SkuMapper {
	return &SkuMapper{}
}

func (m *SkuMapper) SelectCountCtx(ctx context.Context, db *gorm.DB, spuBO bo.SkuBO) (totalCount int64, err error) {
	// 监控
	ctx, span := mysql.StartSpan(ctx, "SkuMapper#SelectCountCtx")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	tx := db.Session(&gorm.Session{SkipDefaultTransaction: true})

	var total int64
	userEntity := entity.SkuEntity{}
	tx = tx.Select(skuAllColumn).Table(userEntity.TableName())
	m.getAllWhereSql(tx, spuBO)
	tx.Count(&total)
	return total, tx.Error
}
func (m *SkuMapper) SelectOneCtx(ctx context.Context, db *gorm.DB, spuBO bo.SkuBO) (skuEntity entity.SkuEntity, err error) {
	// 监控
	ctx, span := mysql.StartSpan(ctx, "SkuMapper#SelectOneCtx")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	tx := db.Session(&gorm.Session{SkipDefaultTransaction: true})
	var resp entity.SkuEntity
	skuInfoEntity := entity.SkuEntity{}
	tx = tx.Select(skuAllColumn).Table(skuInfoEntity.TableName())
	m.getAllWhereSql(tx, spuBO)
	tx.First(&resp)
	return resp, tx.Error
}
func (m *SkuMapper) SelectListCtx(ctx context.Context, db *gorm.DB, spuBO bo.SkuBO) (skuEntity []entity.SkuEntity, err error) {
	// 监控
	ctx, span := mysql.StartSpan(ctx, "SkuMapper#SelectListCtx")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	tx := db.Session(&gorm.Session{SkipDefaultTransaction: true})
	var resp []entity.SkuEntity
	skuInfoEntity := entity.SkuEntity{}
	tx = tx.Select(skuAllColumn).Table(skuInfoEntity.TableName())
	m.getAllWhereSql(tx, spuBO)
	tx = tx.Find(&resp)
	return resp, tx.Error
}

func (m *SkuMapper) getAllWhereSql(db *gorm.DB, skuBo bo.SkuBO) {
	if skuBo.SkuId > 0 {
		db.Where("sku_id = ?", skuBo.SkuId)
	}
	if len(skuBo.SkuIdArr) > 0 {
		db.Where("sku_id in ?", skuBo.SkuIdArr)
	}
	if skuBo.SpuId > 0 {
		db.Where("spu_id = ?", skuBo.SpuId)
	}
	if len(skuBo.SkuName) > 0 || skuBo.SkuName != "" {
		db.Where("sku_name = ?", skuBo.SkuName)
	}
	if len(skuBo.SkuNameAllLike) > 0 || skuBo.SkuNameAllLike != "" {
		db.Where("sku_name like ?", "%"+skuBo.SkuName+"%")
	}
	if len(skuBo.SkuNameArr) > 0 {
		db.Where("sku_name in ?", skuBo.SkuNameArr)
	}
	if len(skuBo.Attrs) > 0 || skuBo.Attrs != "" {
		db.Where("attrs = ?", skuBo.Attrs)
	}
	if len(skuBo.ImgUrl) > 0 || skuBo.ImgUrl != "" {
		db.Where("img_url = ?", skuBo.ImgUrl)
	}
	if skuBo.PriceFee > 0 {
		db.Where("price_fee = ?", skuBo.PriceFee)
	}
	if skuBo.MarketPriceFee > 0 {
		db.Where("market_price_fee = ?", skuBo.MarketPriceFee)
	}
	if len(skuBo.PartyCode) > 0 || skuBo.PartyCode != "" {
		db.Where("party_code = ?", skuBo.PartyCode)
	}
	if len(skuBo.ModelId) > 0 || skuBo.ModelId != "" {
		db.Where("model_id = ?", skuBo.ModelId)
	}
	if skuBo.Weight > 0 {
		db.Where("weight = ?", skuBo.Weight)
	}
	if skuBo.Volume > 0 {
		db.Where("volume = ?", skuBo.Volume)
	}
	if skuBo.Status != 0 {
		db.Where("status = ?", skuBo.Status)
	}
	if skuBo.NeStatus != 0 {
		db.Where("status != ?", skuBo.NeStatus)
	}
	if skuBo.StartTime != nil {
		db.Where("create_time = ?", skuBo.StartTime)
	}
	if skuBo.EndTime != nil {
		db.Where("create_time = ?", skuBo.EndTime)
	}
}

func (m *SkuMapper) BatchInsert(ctx context.Context, engin *gorm.DB, arr []*entity.SkuEntity) (idArr []int64, err error) {
	// 监控
	ctx, span := mysql.StartSpan(ctx, "SkuMapper#BatchInsert")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	tx := engin.Create(arr)
	var ids []int64
	for _, v := range arr {
		ids = append(idArr, v.SkuId)
	}
	return ids, tx.Error
}

func (m *SkuMapper) CountSpuStockCtx(ctx context.Context, engin *gorm.DB, spuIdArr []int64) (doStock []do.SpuStockDO, err error) {
	// 监控
	ctx, span := mysql.StartSpan(ctx, "SkuMapper#CountSpuStockCtx")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	tx := engin.Session(&gorm.Session{SkipDefaultTransaction: true})
	spuEntity := entity.SkuEntity{}
	var returnObj []do.SpuStockDO
	tx.Select(" sum(t2.actual_stock) as actual_stock,sum(t2.lock_stock) as lock_stock ,sum(t2.stock) as stock,sku.spu_id as spu_id").
		Table(spuEntity.TableName()).
		Joins("left join sku_stock t2 on sku.sku_id = t2.sku_id").Where("sku.spu_id in ?", spuIdArr).
		Group("sku.spu_id").Find(&returnObj)
	return returnObj, tx.Error
}

func (m *SkuMapper) SelectSkuListBySpuId(ctx context.Context, engin *gorm.DB, spuId int64) (doArr []do.SkuInfoDO, err error) {
	// 监控
	ctx, span := mysql.StartSpan(ctx, "SkuMapper#SelectSkuListBySpuId")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	tx := engin.Session(&gorm.Session{SkipDefaultTransaction: true})
	var returnObj []do.SkuInfoDO
	tx = tx.Select(skuAllColumnJoin+",t2.stock as stock,t2.actual_stock as actual_stock").Table("sku").
		Joins("left join sku_stock t2 on sku.sku_id = t2.sku_id").Where("sku.spu_id = ?", spuId).
		Find(&returnObj)
	return returnObj, tx.Error
}
func (m *SkuMapper) SelectSkuListBySkuId(ctx context.Context, engin *gorm.DB, skuId int64) (doArr do.SkuInfoDO, err error) {
	// 监控
	ctx, span := mysql.StartSpan(ctx, "SkuMapper#SelectSkuListBySkuId")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	tx := engin.Session(&gorm.Session{SkipDefaultTransaction: true})
	var returnObj do.SkuInfoDO
	tx = tx.Select(skuAllColumnJoin+",t2.stock as stock,t2.actual_stock as actual_stock").Table("sku").
		Joins("left join sku_stock t2 on sku.sku_id = t2.sku_id").Where("sku.sku_id = ?", skuId).
		First(&returnObj)
	return returnObj, tx.Error
}

func (m *SkuMapper) SkuManageForSpuIdCtx(ctx context.Context, engin *gorm.DB, spuIdList []int64, status int) (err error) {
	// 监控
	ctx, span := mysql.StartSpan(ctx, "SkuMapper#SpuManageCtx")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	if len(spuIdList) <= 0 {
		// 不存在直接返回
		return nil
	}
	skuEntity := entity.SkuEntity{}
	tx := engin.Table(skuEntity.TableName()).Where("spu_id in ?", spuIdList).
		Omit("sku_id").Omit("sku_id").
		Update("status", status).Update("update_time", time.Now())
	return tx.Error
}

func (m *SkuMapper) DelSkuForSpuIdCtx(ctx context.Context, engin *gorm.DB, spuIdList []int64) (err error) {
	// 监控
	ctx, span := mysql.StartSpan(ctx, "SpuMapper#DelSkuForSpuIdCtx")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	if len(spuIdList) <= 0 {
		// 不存在直接返回
		return nil
	}
	tx := engin.Table("sku").Where("spu_id in ?", spuIdList).Omit("sku_id").
		Update("status", constans.SpuTakeDown).Update("update_time", time.Now())
	return tx.Error
}
func (m *SkuMapper) DelSkuForSkuIdCtx(ctx context.Context, engin *gorm.DB, skuIdList []int64) (err error) {
	// 监控
	ctx, span := mysql.StartSpan(ctx, "SpuMapper#DelSkuForSkuIdCtx")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	if len(skuIdList) <= 0 {
		// 不存在直接返回
		return nil
	}
	tx := engin.Table("sku").Where("sku_id in ?", skuIdList).Omit("sku_id").
		Update("status", constans.SpuTakeDown).Update("update_time", time.Now())
	return tx.Error
}

func (m *SkuMapper) UpdateCtx(ctx context.Context, engin *gorm.DB, skuEntity *entity.SkuEntity) (err error) {
	// 监控
	ctx, span := mysql.StartSpan(ctx, "SkuMapper#UpdateCtx")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	tx := engin.Where("sku_id = ?", skuEntity.SkuId).Omit("sku_id").
		UpdateColumns(skuEntity)
	return tx.Error
}

func (m *SkuMapper) SkuManageForSkuIdCtx(ctx context.Context, engin *gorm.DB, skuIdList []int64, status int32) (err error) {
	// 监控
	ctx, span := mysql.StartSpan(ctx, "SkuMapper#SkuManageForSkuIdCtx")
	defer func() {
		mysql.EndSpan(span, err)
	}()
	if len(skuIdList) <= 0 {
		// 不存在直接返回
		return nil
	}
	skuEntity := entity.SkuEntity{}
	tx := engin.Table(skuEntity.TableName()).Where("sku_id in ?", skuIdList).
		Omit("sku_id").Omit("sku_id").
		Update("status", status).Update("update_time", time.Now())
	return tx.Error
}
